package com.smartStatus.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartStatus.admin.mapper.SysMenuMapper;
import com.smartStatus.admin.mapper.SysRoleMapper;
import com.smartStatus.admin.service.SysMenuService;
import com.smartStatus.admin.service.SysRoleService;
import com.smartStatus.admin.service.SysUserService;
import com.smartStatus.admin.utils.JoinUtil;
import com.smartStatus.api.entity.SysMenu;
import com.smartStatus.api.entity.SysMenuDetails;
import com.smartStatus.api.entity.SysMenuPermission;
import com.smartStatus.api.entity.SysRole;
import com.smartStatus.api.vo.SysMenuVo;
import com.smartStatus.api.vo.SysUserVO;
import com.smartStatus.core.api.RedisKey;
import com.smartStatus.core.util.R;
import com.smartStatus.security.utils.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName : SysMenuServiceImpl
 * @Author : lby
 * @Date: 2020/12/8 11:04
 * @Description :
 */
@Service
@Slf4j
@AllArgsConstructor
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    private final SysUserService sysUserService;

    private final RedisTemplate redisTemplate;

    private final SysRoleMapper sysRoleMapper;

    @Override
    public List<SysMenuVo> childrenList(SysMenu sysMenu) {
        return baseMapper.childrenList(sysMenu);
    }

    @Override
    /**
     * 分页数据
     */

    public IPage<SysMenu> pageList(Page<SysMenu> page, QueryWrapper<SysMenu> queryWrapper, @Param("sysMenu") SysMenu sysMenu) {
        return baseMapper.pageList(page, queryWrapper, sysMenu);
    }

    /**
     * 菜单添加
     */
    @Override
    public Boolean saveMenus(SysMenu sysMenu) {
        return baseMapper.saveMenus(sysMenu);
    }

    /**
     * 菜单修改
     */
    @Override
    public Boolean editMenu(SysMenu sysMenu) {
        return baseMapper.editMenu(sysMenu);
    }

    /**
     * 菜单删除
     */
    @Override
    public Boolean menuDel(SysMenu sysMenu) {
        return baseMapper.menuDel(sysMenu);
    }


    @Override
    public List<SysMenuDetails> getSubMenus(SysMenuVo sysMenuVo) {
        return baseMapper.getSubMenus(sysMenuVo);
    }

    @Override
    public Integer getParentId(Integer subId) {
        return baseMapper.getParentId(subId);
    }

    @Override
    public R getMenuTree(Boolean flag) {
//        List<SysMenu> o = (List<SysMenu>) redisTemplate.opsForValue().get(RedisKey.MENU_LIST + SecurityUtils.getUser().getId());
//        if (o != null && o.size() > 0) {
//            return R.ok(o);
//        }
        // 根据角色切换路由
        SysUserVO sysUserVO = (SysUserVO) sysUserService.getUserInfo().getData();
        List<SysRole> sysRoles = sysUserVO.getRoleList();
        List<Integer> idList = sysRoles.stream().map(SysRole::getId).collect(Collectors.toList());
        List<SysMenuVo> menuList = baseMapper.getMenuList(idList);
        if (flag){
            menuList.forEach(x->{
                this.recursionTree(x,idList);
            });
        }
        else {
            QueryWrapper<SysMenu> sysMenuQuery = Wrappers.query();
            sysMenuQuery.eq("menu_parent_id",0);
            List<SysMenu> list = this.list(sysMenuQuery);
            menuList=JoinUtil.list(list,SysMenuVo.class);
            menuList.forEach(x->{
                this.recursionTree(x,null);
            });
        }

        // 将菜单存redis中
        redisTemplate.opsForValue().set(RedisKey.MENU_LIST + SecurityUtils.getUser().getId(), menuList, 1, TimeUnit.HOURS);
        return R.ok(menuList);
    }


    /**
     * 递归获取树
     *
     * @param vo
     * @return
     */
    public SysMenuVo recursionTree(SysMenuVo vo,List<Integer> idList) {
        List<SysMenuVo> menuList=baseMapper.getMenuListTree(vo.getId().toString(),idList);
        if (menuList == null || menuList.size() == 0) {
            List<SysMenuVo> emptyList = new ArrayList<>();
            vo.setChildren(emptyList);
            Map<String, Object> map = new HashMap<>();
            map.put("icon", vo.getIcon());
            map.put("noCache", true);
            map.put("title", vo.getName());
            vo.setMeta(map);
            if (vo.getChildren() != null && vo.getChildren().size() > 0) {
                vo.setAlwaysShow(!vo.getHidden());
            }
            return vo;
        }
        List<SysMenuVo> list = JoinUtil.list(menuList, SysMenuVo.class);
        list.forEach(x -> {
            Map<String, Object> map = new HashMap<>();
            map.put("icon", x.getIcon());
            map.put("noCache", true);
            map.put("title", x.getName());
            x.setMeta(map);
            if (x.getChildren() != null && x.getChildren().size() > 0) {
                x.setAlwaysShow(!x.getHidden());
            }
        });
        vo.setChildren(list);
        Map<String, Object> map = new HashMap<>();
        map.put("icon", vo.getIcon());
        map.put("noCache", true);
        map.put("title", vo.getName());
        vo.setMeta(map);
        if (vo.getChildren() != null && vo.getChildren().size() > 0) {
            vo.setAlwaysShow(!vo.getHidden());
        }
        for (SysMenuVo s : list) {
            vo = this.recursionTree(s,idList);
        }
        return vo;
    }


    @Override
    public R deleteMenuTree(Integer userId) {
        String key = RedisKey.MENU_LIST + userId;
        Object o = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(o != null ? o.toString() : null)) {
            Boolean delete = redisTemplate.delete(key);
            if (delete) {
                return R.ok();
            } else {
                return R.failed("缓存删除失败");
            }
        } else {
            return R.failed("未获取到当前用户缓存");
        }
    }


    @Override
    public R saveMenuList(SysMenuVo sysMenuVo) {
        // 区分不同类型  0目录 1：菜单 2 按钮
        Integer type = sysMenuVo.getType();
//        sysMenuVo.setRedirect("noredirect");
        sysMenuVo.setComponentPath("Layout");
        sysMenuVo.setLabel(sysMenuVo.getName());
        // 目录
        if (type==0){
            sysMenuVo.setComponent("Layout");
            sysMenuVo.setMenuParentId(0);
            sysMenuVo.setHasChildren(true);
        }
        // 权限
        if (type==2){
            String permissionName=sysMenuVo.getName();
            Integer menuId=sysMenuVo.getMenuParentId();
            QueryWrapper<SysRole> sysRoleQuery = Wrappers.query();
            List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleQuery);
            sysRoles.forEach(x->{
                SysMenuPermission sysMenuPermission = new SysMenuPermission();
                sysMenuPermission.setMenuId(menuId);
                sysMenuPermission.setPermission(permissionName);
                sysMenuPermission.setChecked("0");
                sysMenuPermission.setRoleId(x.getId().toString());
                sysMenuPermission.insert();
            });
            return R.ok();
        }
        this.save(sysMenuVo);
        return R.ok();
    }
}
